#include "BlockRenderers.h"
#include "..\Math\Colorb.h"
#include "..\Math\Point2.h"
#include "ITexture.h"
#include <algorithm>
#include <iomanip>

void Fonts::LoadGlyphSizes(const std::shared_ptr<byte> &data)
{
	for (int i = 0; i < UINT16_MAX; ++i)
		_glyphSizes[i].SetValues(data.get()[i]);

	if (!_createdTextures)
	{
		_createdTextures = true;
		LoadGlyphs();
	}

	std::shared_ptr<Colorb> imageData(new Colorb[_default->GetWidth() * _default->GetHeight()]);
	_default->BlitData(imageData.get());
	const int &scale = _default->GetScale();
	const int charSize = 8 * scale;

	memset(_defaultSizes, 0, sizeof(_defaultSizes));

	for (int y = 0; y < 16; ++y)
		for (int x = 0; x < 16; ++x)
		{
			int index = (y * 16) + x;

			Point2i topLeft(x * charSize, y * charSize);
			Point2i bottomRight(topLeft.X + charSize, topLeft.Y + charSize);

			int startCol = -1, endCol = -1;

			for (int xx = bottomRight.X - 1; xx >= topLeft.X && endCol == -1; --xx)
				for (int yy = bottomRight.Y - 1; yy >= topLeft.Y; --yy)
				{
					int pixel = (yy * _default->GetWidth()) + xx;
					auto &c = imageData.get()[pixel];

					if (c.A != 0)
					{
						endCol = xx - topLeft.X;
						break;
					}
				}

			for (int xx = topLeft.X; xx < bottomRight.X && startCol == -1; ++xx)
				for (int yy = topLeft.Y; yy < bottomRight.Y; ++yy)
				{
					int pixel = (yy * _default->GetWidth()) + xx;
					auto &c = imageData.get()[pixel];

					if (c.A != 0)
					{
						startCol = xx - topLeft.X;
						break;
					}
				}

			if (endCol == -1)
				endCol = 0;
			if (startCol == -1)
				startCol = 0;

			_defaultSizes[index].SetValues(startCol, endCol);
		}
}

void Fonts::LoadGlyphs()
{
	_default = _renderers->GetTexture("font\\default.png");

	for (int i = 0; i < 256; ++i)
	{
		std::stringstream stream;
		stream << std::setfill ('0') << std::setw(2) << std::uppercase << std::hex << i;

		_glyphs[i] = _renderers->GetTexture(wxString("font\\glyph_") << stream.str() << ".png");
	}
}

std::pair<std::pair<Point2i, GlyphSize>, ITexture*> Fonts::GetDataForChar(const wxChar16 &c, const bool &allGlyphs)
{
	if (c < 256 && !allGlyphs)
		return std::make_pair(std::make_pair(Point2i((c % 16) * (8 * _default->GetScale()), (c / 16) * (8 * _default->GetScale())), this->_defaultSizes[c]), this->_default);

	union
	{
		wxChar16 asUTF16;
		struct
		{
			uint8_t low, high;
		};
	} bits;
	bits.asUTF16 = c;

	return std::make_pair(std::make_pair(Point2i((bits.low % 16) * (16 * this->_glyphs[bits.high]->GetScale()), (bits.low / 16) * (16 * this->_glyphs[bits.high]->GetScale())), this->_glyphSizes[c]), this->_glyphs[bits.high]);
}